home *** CD-ROM | disk | FTP | other *** search
/ Collection of Tools & Utilities / Collection of Tools and Utilities.iso / comm / uwpc201.zip / UW-SRC.ZIP / UWFTP.C < prev    next >
C/C++ Source or Header  |  1991-05-08  |  11KB  |  341 lines

  1. /*-------------------------------------------------------------------------
  2.  
  3.   UWFTP.C - FTP server for use with the UW/PC communications program.
  4.  
  5.   This server is quite "dumb".  Most of the brains is in the client in
  6.   the UW/PC program.  This protocol is not conformant with the standard
  7.   Internet FTP protocol - it is for transmission across a serial link only.
  8.  
  9.   To compile this server, execute the following:
  10.  
  11.                 cc -o uwftp uwftp.c
  12.  
  13.     This file is part of UW/PC - a multi-window comms package for the PC.
  14.     Copyright (C) 1990-1991  Rhys Weatherley
  15.  
  16.     This program is free software; you can redistribute it and/or modify
  17.     it under the terms of the GNU General Public License as published by
  18.     the Free Software Foundation; either version 1, or (at your option)
  19.     any later version.
  20.  
  21.     This program is distributed in the hope that it will be useful,
  22.     but WITHOUT ANY WARRANTY; without even the implied warranty of
  23.     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  24.     GNU General Public License for more details.
  25.  
  26.     You should have received a copy of the GNU General Public License
  27.     along with this program; if not, write to the Free Software
  28.     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  29.  
  30.   Revision History:
  31.   ================
  32.  
  33.    Version  DD/MM/YY  By  Description
  34.    -------  --------  --  --------------------------------------
  35.      1.0    13/04/91  RW  Original Version of UWFTP.C
  36.      1.1    07/05/91  RW  Being serious writing of the server.
  37.  
  38.   You may contact the author by:
  39.   =============================
  40.  
  41.    e-mail: rhys@cs.uq.oz.au
  42.      mail: Rhys Weatherley
  43.            5 Horizon Drive
  44.            Jamboree Heights
  45.            Queensland 4074
  46.            Australia
  47.  
  48. -------------------------------------------------------------------------*/
  49.  
  50. #include <stdio.h>              /* Standard I/O routines */
  51. #include <sys/types.h>          /* System type declarations */
  52. #include <sys/time.h>           /* Time value declarations */
  53. #include <sgtty.h>              /* Terminal control declarations */
  54. #include <signal.h>             /* Signal handling routines */
  55.  
  56. /*
  57.  * Global declarations for this module.
  58.  */
  59. #define HOST_LEN        256        /* Length of host name buffers */
  60. char    hostname[HOST_LEN];        /* Name of host from "gethostname" */
  61. struct  sgttyb  terminal;        /* Saved terminal statistics */
  62. #define CANCEL_CHAR     ('X' & 0x1F)    /* Character to cancel transfer */
  63. #define    NO_CHAR        (-2)        /* From "waitfortimeout" function */
  64. #define STARTUP_SEQ    "\001\076F"    /* Startup message for client */
  65. #define    MAX_PLEN    94        /* Maximum packet length */
  66. struct    packet    {
  67.           int    number;        /* Packet number */
  68.           char    type;        /* Type of packet */
  69.           int    length;        /* Packet length */
  70.           int    checksum;    /* Checksum value */
  71.           char    data[MAX_PLEN];    /* Data in the packet */
  72.         };
  73. struct    packet    RecvPacket;        /* Received packet */
  74. struct    packet    SendPacket;        /* Transmitted packet */
  75. char    tempbuf[BUSIZ];            /* Temporary reception buffer */
  76. #define    TOCHAR(x)    ((x) + ' ')    /* Convert numeric value to char */
  77. #define    FROMCHAR(x)    ((x) - ' ')    /* Convert character to numeric val */
  78. FILE    *tfile=NULL;            /* Current transfer file */
  79.  
  80. main    (argc,argv)
  81. int     argc;
  82. char    *argv[];
  83. {
  84.   time_t currenttime;
  85.   struct sgttyb newterm;
  86.   int ch;
  87.  
  88.   /* Check to make sure both stdin and stdout are terminals */
  89.   if (!isatty (0) || !isatty (1))
  90.     {
  91.       fprintf (stderr,
  92.         "Standard input and output must be terminals for UWFTP.\n");
  93.       exit (1);
  94.     } /* if */
  95.  
  96.   /* Initialise the terminal input into cbreak and non-echo mode */
  97.   gtty (0,&terminal);
  98.   newterm = terminal;
  99.   newterm.sg_flags |= CBREAK;
  100.   newterm.sg_flags &= ~ECHO;
  101.   stty (0,&newterm);
  102.  
  103.   /* Turn off signals that may cause problems during processing */
  104.   signal (SIGINT,SIG_IGN);      /* Interrupt signal */
  105. #ifdef  SIGTSTP                 /* Conditional just in case :-) */
  106.   signal (SIGTSTP,SIG_IGN);     /* Stop signal from keyboard */
  107. #endif
  108.  
  109.   /* Send the startup sequence and wait until a valid response is received */
  110.   ch = ' ';
  111.   while (ch != CANCEL_CHAR && ch != 'A')
  112.     ch = sendstring (STARTUP_SEQ,1);
  113.   if (ch == CANCEL_CHAR)
  114.     abortftp ();                /* ^X received - abort the transfer */
  115.  
  116.   /* We are now connected to the client - output the welcome message */
  117.   if (gethostname (hostname,HOST_LEN))
  118.     strcpy (hostname,"process");
  119.   time (¤ttime);
  120.   printf ("HHHHH  UWFTP server %s started on %s\n\n",hostname,
  121.           ctime (¤ttime));
  122.   fflush (stdout);
  123.  
  124.   /* Go into the client service mode, waiting for file/command requests */
  125.   serveclient ();
  126. } /* main */
  127.  
  128. /*
  129.  * Wait for a particular timeout for a character to arrive
  130.  * on the server's standard input.  Returns the character or
  131.  * NO_CHAR if no character was received within the timeout period.
  132.  */
  133. int    waitfortimeout (timeout)
  134. int    timeout;
  135. {
  136.   fd_set readfds;
  137.   struct timeval timeoutst;
  138.   timeoutst.tv_sec = timeout;
  139.   timeoutst.tv_usec = 0;
  140.   FD_ZERO (&readfds);
  141.   FD_SET (0,&readfds);
  142.   if (select (1,&readfds,NULL,NULL,&timeoutst) > 0)
  143.     return (getchar ());
  144.    else
  145.     return (NO_CHAR);
  146. } /* waitfortimeout */
  147.  
  148. /*
  149.  * Send (and resend) a string to the client machine until a
  150.  * character is received from the client program which is
  151.  * returned from this function.  CR and LF characters are
  152.  * ignored in the input.
  153.  */
  154. int    sendstring (packet,timeout)
  155. char    *packet;
  156. int     timeout;
  157. {
  158.   int ch;
  159.   while (1)
  160.     {
  161.       printf ("%s",packet);        /* Send the packet to the client */
  162.       fflush (stdout);
  163.       ch = '\r';
  164.       while (ch == '\r' || ch == '\n')    /* Wait for timeout/non-CRLF char */
  165.         ch = waitfortimeout (timeout);
  166.       if (ch != NO_CHAR)        /* If a character received, exit */
  167.         return (ch);
  168.     } /* while */
  169. } /* sendstring */
  170.  
  171. /*
  172.  * Receive a packet from the client program.  Returns
  173.  * non-zero for a valid packet or zero if invalid/timeout.
  174.  */
  175. int    receivepacket (timeout)
  176. int    timeout;
  177. {
  178.   int ch=NO_CHAR;
  179.   int posn=0;
  180.   int save;
  181.  
  182.   /* Wait until the next packet starts */
  183.   while (timeout > 0 && (ch == NO_CHAR || ch == '\r' || ch == '\n'))
  184.     {
  185.       ch = waitfortimeout (1);    /* Wait for the next character */
  186.       if (ch == CANCEL_CHAR)
  187.         abortftp ();
  188.       if (ch == NO_CHAR)
  189.         --timeout;        /* Decrease timeout if none yet */
  190.     } /* while */
  191.  
  192.   /* Read characters into the temporary reception buffer */
  193.   while (posn < (BUFSIZ - 1) && ch != '\r' && ch != '\n')
  194.     {
  195.       tempbuf[posn++] = ch;
  196.       ch = waitfortimeout (3);    /* Wait for the next packet character */
  197.       if (ch == CANCEL_CHAR)
  198.         abortftp ();
  199.     } /* while */
  200.   if (posn >= (BUFSIZ - 1))
  201.     return (0);            /* Packet too long - abort */
  202.   tempbuf[posn] = '\0';
  203.   posn = 0;
  204.  
  205.   /* Decode the received packet header into its components */
  206.   if (!tempbuf[posn])
  207.     return (0);
  208.   RecvPacket.number = FROMCHAR(tempbuf[posn++] & 255);
  209.   if (RecvPacket.number < 0 || RecvPacket.number >= MAX_PLEN)
  210.     return (0);
  211.   if (!tempbuf[posn])
  212.     return (0);
  213.   RecvPacket.type = tempbuf[posn++] & 255;
  214.   if (!tempbuf[posn])
  215.     return (0);
  216.   RecvPacket.length = FROMCHAR(tempbuf[posn++] & 255);
  217.   if (RecvPacket.length < 0 || RecvPacket.length >= MAX_PLEN)
  218.     return (0);
  219.   if (!tempbuf[posn])
  220.     return (0);
  221.   RecvPacket.checksum = FROMCHAR(tempbuf[posn++] & 255);
  222.   if (RecvPacket.checksum < 0 || RecvPacket.checksum >= MAX_PLEN)
  223.     return (0);
  224.   if (!tempbuf[posn])
  225.     return (0);
  226.   ch = FROMCHAR(tempbuf[posn++] & 255);
  227.   if (ch < 0 || ch >= MAX_PLEN)
  228.     return (0);
  229.   RecvPacket.checksum += ch * MAX_PLEN;
  230.  
  231.   /* Decode the data portion of the packet */
  232.   save = 0;
  233.   while (tempbuf[posn] && save < RecvPacket.length)
  234.     {
  235.       ch = tempbuf[posn++];
  236.       if (ch < ' ' || ch >= 0177)
  237.         return (0);        /* Illegal character in packet */
  238.       if (ch != '#')
  239.         RecvPacket.data[save++] = ch;
  240.        else
  241.         {
  242.       /* Process an escaped character */
  243.       ch = tempbuf[posn++];
  244.